package fr.jade.reflex.control.content;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalContentException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.control.LifeCycleController;
import org.objectweb.fractal.api.factory.InstantiationException;

import fr.jade.fraclite.InitializationContext;
import fr.jade.fraclite.control.content.BasicContentController;
import fr.jade.reflex.api.control.ContentNotificationController;
import fr.jade.reflex.api.control.ReflexController;
import fr.jade.reflex.util.Reflex;
import fr.jade.util.log.Logger;
import fr.jade.util.log.config.LogReflex;

/**
 * Provides an implementation of the
 * {@link org.objectweb.fractal.api.control.ContentController} interface which
 * manages the causal connection with the dual level (i.e meta/execution) : any
 * content operation performed on the current component is notified to the
 * content controller of dual component.
 * 
 * @author Fabienne Boyer 18/05/05
 * @author Sylvain Sicard
 * @contact Fabienne.Boyer@inrialpes.fr
 */

public class ReflexContentController extends BasicContentController implements ContentNotificationController {


  public ReflexController weaveableRC;

  public void initFcController (final InitializationContext ic) throws InstantiationException {
    Logger.println(LogReflex.debug, "ReflexContentController : init");
    weaveableRC = (ReflexController) ic.getInterface("reflex-controller");
    super.initFcController(ic);
  }
  
  protected ContentNotificationController getDualCtrl() {
    assert weaveableRC != null : "Component must have a ReflexController";
    Component dual = weaveableRC.getCmpRef();
    assert dual != null : "Component must have a dual";
    ContentNotificationController dualCtrl = null;
    try {
      dualCtrl = Reflex.getContentNotificationController(dual);
    } catch (NoSuchInterfaceException ignored) {}
    assert dualCtrl != null : "Dual component must have a ContentNotificationController";
    return dualCtrl;
  }
  
  // -------------------------------------------------------------------------
  // Fields and methods added and overriden by the mixin class
  // -------------------------------------------------------------------------

  /**
   * Calls the overriden addFcSubComponent method and then notifies the dual
   * level of the content modification.
   * 
   * @param subComp
   *            the component to be added inside this component.
   * @throws IllegalContentException
   *             if the given component cannot be added inside this component.
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */

  public void addFcSubComponent(final Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
      addFcSubComponentNotification(subComponent);
      getDualCtrl().addFcSubComponentNotification(Reflex.getDualComponent(subComponent));
  }

  /**
   * Calls the overriden addFcSubComponent method
   * 
   * @param subComp
   *            the component to be added inside this component.
   * @throws IllegalContentException
   *             if the given component cannot be added inside this component.
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */
  public void addFcSubComponentNotification(Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
      Logger.println(LogReflex.debug, "addFcSubComponentNotification ");
      super.addFcSubComponent(subComponent);
  }

  /**
   * Calls the overriden method and then notifies the dual level of the
   * content modification.
   * 
   * @param subComponent
   *            the component to be removed from this component.
   * @throws IllegalContentException
   *             if the given component cannot be removed from this component.
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */

  public void removeFcSubComponent(final Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
      removeFcSubComponentNotification(subComponent);
      getDualCtrl().removeFcSubComponentNotification(Reflex.getDualComponent(subComponent));    
  }

  /**
   * Calls the overriden removeFcSubComponent method
   * 
   * @param subComp
   *            the component to be removed inside this component.
   * @throws IllegalContentException
   *             if the given component cannot be removed inside this
   *             component.
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */
  public void removeFcSubComponentNotification(Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
      Logger.println(LogReflex.debug, "removeFcSubComponentNotification ");
      super.removeFcSubComponent(subComponent);
  }

  @Override
  public void rawRemoveFcSubComponentNotification(Component subComponent) throws IllegalContentException, IllegalLifeCycleException {
    if(innerImpl == null){
      fcSubComponents.remove(subComponent);
    }else{
      innerImpl.removeFcSubComponent(subComponent);
    }
  }

  
}
